#include "evaluator.h"

#define DEFAULT_DEPTH 5
#define DEFAULT_END_GAME 12

#define N_BESTMOVES 1
#define TRIVIAL_DEPTH 3
#define END_GAME_TRIVIAL_DEPTH 6

/* order moves using the best n policy
   #in, out# moves      ... input list of moves and output a reordered list
   #in, out# child      ... child game after each move has been applied
   #in#      mCount     ... number of moves
   #in#      player     ... the current player
   #in#      stage      ... stage the game is at                            */
void OrderMoves(int moves[], gameState children[], int mCount, BoardState player, int stage);
    
/* Compute negamax score for the node
   #in#  node       ... current game state
   #in#  player     ... player to move
   #in#  depth      ... depth of the subtree
   #in#  alpha      ... lower bound for optimum score
   #in#  beta       ... upper bound for optimum score
   #in#  stage      ... which stage the game is at (= number of pieces - 5)
   #in#  pass_move  ... whether the previous player passed his move
   return           ... minimax score of the current node                   */    
int NegaScout(gameState node, BoardState player, int depth, int alpha, int beta, int stage, bool pass_move);

/* Compute negamax score for the node until a terminal state reached
   #in#  node       ... current game state
   #in#  player     ... player to move
   #in#  alpha      ... lower bound for optimum score
   #in#  beta       ... upper bound for optimum score
   #in#  stage      ... number of pieces - 5
   #in#  pass_move  ... whether the previous player passed his move
   return           ... minimax score of the current node                   */ 
int NegaScoutEndGame(gameState node, BoardState player, int alpha, int beta, int stage, bool pass_move);

/* Completely solve the end game */
int SolveEndgame(gameState gs, Board player, int stage);

/* choose the best move 
   #in#  b          ... current board state
   #in#  player     ... current player
   return           ... best move (x, y) in the format x*10 + y             */
int chooseMove(Board & b, BoardState player, int depth = DEFAULT_DEPTH, int endgame = DEFAULT_END_GAME);


/* test the agent
   #in#  b          ... current board state
   #in#  player     ... current player                                      */
void testClient(Board & b, BoardState player);


void initialiseAI();
